import {
  awaitTimeout,
  IHttpResponse,
  mergeInLeft,
  RuntimeError,
  mergeDefaultInLeft,
} from '@ibiz-template/core';
import {
  ControlVO,
  FormNotifyState,
  hasDeCodeName,
  IEditFormController,
  IEditFormEvent,
  IEditFormState,
} from '@ibiz-template/runtime';
import { IDEEditForm } from '@ibiz/model-core';
import { FormController } from '../form';
import { EditFormService } from './edit-form.service';

/**
 * 编辑表单控制器
 *
 * @author chitanda
 * @date 2022-08-03 11:08:20
 * @export
 * @class EditFormController
 * @extends {FormController<EditFormModel>}
 */
export class EditFormController
  extends FormController<IDEEditForm, IEditFormState, IEditFormEvent>
  implements IEditFormController
{
  /**
   * 编辑表单服务
   * @author lxm
   * @date 2023-05-15 11:03:34
   * @type {EditFormService}
   */
  service!: EditFormService;

  /**
   * 是否是新建数据
   *
   * @author lxm
   * @date 2022-08-31 22:08:44
   * @type {boolean}
   */
  isNewData: boolean = false;

  /**
   * 初始化方法
   *
   * @author lxm
   * @date 2022-08-22 22:08:16
   * @protected
   * @returns {*}  {Promise<void>}
   */
  protected async onCreated(): Promise<void> {
    await super.onCreated();
    // 实例部件服务
    this.service = new EditFormService(this.model);
    await this.service.init(this.context);
  }

  /**
   * 部件加载数据行为
   *
   * @author lxm
   * @date 2022-08-19 14:08:50
   */
  async load(): Promise<IData> {
    this.isNewData = !hasDeCodeName(this.context, this.model.appDataEntityId!);
    const queryParams = { ...this.params };

    // 新建默认值给到graft接口，接口会回来
    let params: IData = {};
    if (this.isNewData) {
      params = await this.getDraftParams();
      Object.assign(queryParams, params);
    }

    await this.startLoading();
    let res;
    try {
      res = this.isNewData
        ? await this.service.getDraft(this.context, queryParams)
        : await this.service.get(this.context, queryParams);
    } finally {
      await this.endLoading();
    }

    if (this.isNewData) {
      // !getDraft的时候不替换，进行合并，空值不覆盖
      mergeInLeft(this.data, res.data);
    } else {
      this.state.data = res.data;
    }
    this.state.modified = false;
    this.state.data = res.data;
    mergeDefaultInLeft(this.data, params);
    this.formStateNotify(
      this.isNewData ? FormNotifyState.DRAFT : FormNotifyState.LOAD,
    );

    await this.evt.emit(
      this.isNewData ? 'onLoadDraftSuccess' : 'onLoadSuccess',
      undefined,
    );
    this.state.isLoaded = true;
    return this.data;
  }

  /**
   * 保存表单数据
   *
   * @author lxm
   * @date 2022-08-31 22:08:40
   */
  async save(): Promise<IData> {
    // 如果数据正在处理中，则延迟保存
    if (this.state.processing) {
      const data = await awaitTimeout(500, this.save.bind(this));
      return data!;
    }

    const isValid = await this.validate();
    if (!isValid) {
      throw new RuntimeError('请检查表单填写！');
    }
    await this.startLoading();
    let res;
    try {
      res = this.isNewData
        ? await this.service.create(this.context, this.data)
        : await this.service.update(this.context, this.data);
    } finally {
      await this.endLoading();
    }
    // 保存结束后的事件
    if (res.data) {
      mergeInLeft(this.data, res.data);
    }
    this.state.modified = false;
    await this.evt.emit('onSaveSuccess', undefined);
    this.isNewData = false;
    this.formStateNotify(FormNotifyState.SAVE);
    ibiz.message.success(`${this.data.srfmajortext || ''}保存成功`);
    return this.data;
  }

  /**
   * 删除表单数据
   *
   * @author lxm
   * @date 2022-09-01 09:09:36
   * @returns {*}
   */
  async remove(): Promise<boolean> {
    // 新建数据清空数据
    let res: IHttpResponse | undefined;
    let ok: boolean = false;
    if (!this.isNewData) {
      ok = await ibiz.modal.confirm({
        title: '提示',
        desc: '确认删除吗？',
      });
      if (ok) {
        await this.startLoading();
        try {
          res = await this.service.remove(this.context, this.params);
        } finally {
          await this.endLoading();
        }
        await this.evt.emit('onRemoveSuccess', undefined);
        this.state.data = new ControlVO();
        this.state.modified = false;
        ok = res.ok;
      } else {
        // 取消不抛事件
        return false;
      }
    }
    return ok;
  }

  /**
   * 执行返回行为
   *
   * @author lxm
   * @date 2022-09-01 09:09:36
   * @returns {*}
   */
  async goBack(): Promise<void> {
    await this.startLoading();
    let res;
    try {
      res = await this.service.goBack(this.context, this.data);
    } finally {
      await this.endLoading();
    }
    // 合并后台返回数据
    if (res.data) {
      mergeInLeft(this.data, res.data);
    }
  }

  /**
   * 表单项更新
   *
   * @author lxm
   * @date 2022-09-15 21:09:13
   * @param {string} methodName 更新实体方法
   * @param {string[]} updateItems 更新项名称集合
   */
  async updateFormItem(formItemUpdateId: string): Promise<void> {
    const formItemUpdate = this.model.deformItemUpdates?.find(
      item => item.id === formItemUpdateId,
    );

    if (!formItemUpdate) {
      throw new RuntimeError(`没找到${formItemUpdateId}表单项更新`);
    }

    const { appDEMethodId, defiupdateDetails } = formItemUpdate;
    const updateItems = defiupdateDetails!.map(item => item.id!);

    const params = { ...this.params, ...this.data.getOrigin() };
    const res = await this.service.updateFormItem(
      appDEMethodId!,
      this.context,
      params,
    );
    const result = res.data;
    if (result && updateItems?.length) {
      await Promise.all(
        updateItems.map(itemName =>
          this.setDataValue(itemName, result[itemName]),
        ),
      );
    }
  }

  /**
   * 工作流启动(调用前先确保调用保存)
   *
   * @author lxm
   * @date 2022-10-08 18:10:41
   * @param {IParams} [extraParams={}] 不走工作流启动视图时使用
   * @returns {*}  {Promise<void>}
   */
  async wfStart(extraParams: IParams = {}): Promise<void> {
    const isValid = await this.validate();
    if (!isValid) {
      throw new RuntimeError('请检查表单填写！');
    }
    await this.startLoading();
    try {
      await this.service.wfStart(
        this.context,
        {
          ...this.params,
          ...extraParams,
        },
        this.data,
      );
    } finally {
      await this.endLoading();
    }
    ibiz.message.success('流程启动成功');
  }

  /**
   * 工作流提交(调用前先确保调用保存)
   *
   * @author lxm
   * @date 2022-10-08 18:10:56
   * @param {IParams} [extraParams={}] 不走工作流操作视图时使用
   * @returns {*}  {Promise<void>}
   */
  async wfSubmit(extraParams: IParams = {}): Promise<void> {
    const isValid = await this.validate();
    if (!isValid) {
      throw new RuntimeError('请检查表单填写！');
    }
    await this.startLoading();
    try {
      await this.service.wfSubmit(
        this.context,
        {
          ...this.params,
          ...extraParams,
        },
        this.data,
      );
    } finally {
      await this.endLoading();
    }
    ibiz.message.success('流程提交成功');
  }
}
